/*
 * @(#)ServiceIndexNameFactory.java   1.0  2016年11月28日
 * 
 * Copyright (c)	2014-2020. All Rights Reserved.	GuangZhou hhmk Technology Company LTD.
 */
package com.swift.dao.es.factory;

import java.io.IOException;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.HttpAsyncResponseConsumerFactory;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.swift.core.env.EnvDecode;
import com.swift.exception.extend.SystemException;
import com.swift.util.type.TypeUtil;
import com.swift.util.type.UrlUtil;

/**
 * 需要导入的数据表名称
 *
 * @author zhengjiajin
 * @version 1.0 2016年11月28日
 */
@Service
public class ServiceIndexNameFactory {
    private final static Logger log = LoggerFactory.getLogger(ServiceIndexNameFactory.class);

    @Value("${es.hostname:}")
    private String HOSTNAME;

    @Value("${es.port:9200}")
    private Integer PORT = 9200;

    @Value("${es.scheme:http}")
    private String SCHEME = "http";

    @Value("${es.username:}")
    private String USERNAME;

    @Value("${es.password:}")
    private String PASSWORD;
    //如:http://es-***.elasticsearch.aliyuncs.com:9200?username=xxx&password=xxx&index_dev=test_
    @Value("${es.url:}")
    private String url;

    private RestHighLevelClient highClient;
    
    public static final RequestOptions COMMON_OPTIONS;
    
    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
        // 默认缓冲限制为100MB
        builder.setHttpAsyncResponseConsumerFactory(
                new HttpAsyncResponseConsumerFactory
                        .HeapBufferedResponseConsumerFactory(100 * 1024 * 1024));
        COMMON_OPTIONS = builder.build();
    }

    @PostConstruct
    public void init() {
        try {
            if(TypeUtil.isNotNull(url)) formatEsUrl();
            if (TypeUtil.isNull(HOSTNAME)) return;
            if (TypeUtil.isNull(USERNAME)) return;
            final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(getUserName(), getPassword()));

            RestClientBuilder builder = RestClient.builder(new HttpHost(HOSTNAME, PORT))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                });
            highClient = new RestHighLevelClient(builder);
        } catch (Throwable ex) {
            log.error("es连接异常" + HOSTNAME + ";" + USERNAME + "出错", ex);
        }
    }
    
    private void formatEsUrl() {
        String scheme = getUrlScheme();
        String hostName = getUrlHostName();
        String userName = getUrlUsername();
        String password = getUrlPassword();
        Integer port = getUrlPort();
        if(TypeUtil.isNotNull(scheme)) setSCHEME(scheme);
        if(TypeUtil.isNotNull(hostName)) setHOSTNAME(hostName);
        if(TypeUtil.isNotNull(userName)) setUSERNAME(userName);
        if(TypeUtil.isNotNull(password)) setPASSWORD(password);
        if(TypeUtil.isNotNull(port))  setPORT(port);
    }
    

    private String getUrlScheme() {
        if(TypeUtil.isNull(url)) return null;
        if(url.indexOf("://")==-1) return null;
        String scheme = url.substring(0, url.indexOf("://"));
        if(TypeUtil.isNull(scheme)) return null;
        return scheme.toLowerCase();
    }

    private String getUrlHostName() {
        if(TypeUtil.isNull(url)) return null;
        String domain = UrlUtil.urlPage(url);
        if(domain.indexOf("://")!=-1) domain=domain.substring(domain.indexOf("://")+3);
        if(domain.indexOf(":")!=-1) domain=domain.substring(0,domain.indexOf(":"));
        return domain;
    }

    private String getUrlUsername() {
        if(TypeUtil.isNull(url)) return null;
        Map<String, String> map = UrlUtil.URLRequest(url);
        if(TypeUtil.isNull(map)) return null;
        return map.get("username");
    }

    private String getUrlPassword() {
        if(TypeUtil.isNull(url)) return null;
        Map<String, String> map = UrlUtil.URLRequest(url);
        if(TypeUtil.isNull(map)) return null;
        return map.get("password");
    }

    private Integer getUrlPort() {
        if(TypeUtil.isNull(url)) return null;
        String domain = UrlUtil.urlPage(url);
        if(domain.indexOf("://")!=-1) domain=domain.substring(domain.indexOf("://")+3);
        if(domain.indexOf(":")==-1) return null;
        domain=domain.substring(domain.indexOf(":")+1);
        return TypeUtil.toInt(domain);
    }

    public RestHighLevelClient getClient() {
        if (this.highClient == null) throw new SystemException("未建产ES连接，不能操作");
        return this.highClient;
    }
    
    public boolean isConnect() {
        if (this.highClient == null)  return false;
        return true;
    }
    
    public void restart() {
        destroy();
        init();
    }
    
    private String getPassword() {
        return EnvDecode.decode(PASSWORD);
    }
    
    private String getUserName() {
        return EnvDecode.decode(USERNAME);
    }

    @PreDestroy
    protected void destroy() {
        try {
            this.highClient.close();
        } catch (IOException e) {
        }
    }

    /**
     * @return the hOSTNAME
     */
    public String getHOSTNAME() {
        return HOSTNAME;
    }

    /**
     * @param hOSTNAME the hOSTNAME to set
     */
    public void setHOSTNAME(String hOSTNAME) {
        HOSTNAME = hOSTNAME;
    }

    /**
     * @return the pORT
     */
    public Integer getPORT() {
        return PORT;
    }

    /**
     * @param pORT the pORT to set
     */
    public void setPORT(Integer pORT) {
        PORT = pORT;
    }

    /**
     * @return the sCHEME
     */
    public String getSCHEME() {
        return SCHEME;
    }

    /**
     * @param sCHEME the sCHEME to set
     */
    public void setSCHEME(String sCHEME) {
        SCHEME = sCHEME;
    }

    /**
     * @return the uSERNAME
     */
    public String getUSERNAME() {
        return USERNAME;
    }

    /**
     * @param uSERNAME the uSERNAME to set
     */
    public void setUSERNAME(String uSERNAME) {
        USERNAME = uSERNAME;
    }

    /**
     * @return the pASSWORD
     */
    public String getPASSWORD() {
        return PASSWORD;
    }

    /**
     * @param pASSWORD the pASSWORD to set
     */
    public void setPASSWORD(String pASSWORD) {
        PASSWORD = pASSWORD;
    }

    /**
     * @return the url
     */
    public String getUrl() {
        return url;
    }

    /**
     * @param url the url to set
     */
    public void setUrl(String url) {
        this.url = url;
    }
    
}
